home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / procssng / ccs / ccs-11tl.lha / lbl / sun / jpeg / lib / jcpipe.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-02-09  |  26.8 KB  |  756 lines

  1. /*
  2.  * jcpipe.c
  3.  *
  4.  * Copyright (C) 1991, 1992, Thomas G. Lane.
  5.  * This file is part of the Independent JPEG Group's software.
  6.  * For conditions of distribution and use, see the accompanying README file.
  7.  *
  8.  * This file contains compression pipeline controllers.
  9.  * These routines are invoked via the c_pipeline_controller method.
  10.  *
  11.  * There are four basic pipeline controllers, one for each combination of:
  12.  *    single-scan JPEG file (single component or fully interleaved)
  13.  *  vs. multiple-scan JPEG file (noninterleaved or partially interleaved).
  14.  *
  15.  *    optimization of entropy encoding parameters
  16.  *  vs. usage of default encoding parameters.
  17.  *
  18.  * Note that these conditions determine the needs for "big" arrays:
  19.  * multiple scans imply a big array for splitting the color components;
  20.  * entropy encoding optimization needs a big array for the MCU data.
  21.  *
  22.  * All but the simplest controller (single-scan, no optimization) can be
  23.  * compiled out through configuration options, if you need to make a minimal
  24.  * implementation.
  25.  */
  26.  
  27. #include "jinclude.h"
  28.  
  29.  
  30. /*
  31.  * About the data structures:
  32.  *
  33.  * The processing chunk size for downsampling is referred to in this file as
  34.  * a "row group": a row group is defined as Vk (v_samp_factor) sample rows of
  35.  * any component after downsampling, or Vmax (max_v_samp_factor) unsubsampled
  36.  * rows.  In an interleaved scan each MCU row contains exactly DCTSIZE row
  37.  * groups of each component in the scan.  In a noninterleaved scan an MCU row
  38.  * is one row of blocks, which might not be an integral number of row groups;
  39.  * for convenience we use a buffer of the same size as in interleaved scans,
  40.  * and process Vk MCU rows in each burst of downsampling.
  41.  * To provide context for the downsampling step, we have to retain the last
  42.  * two row groups of the previous MCU row while reading in the next MCU row
  43.  * (or set of Vk MCU rows).  To do this without copying data about, we create
  44.  * a rather strange data structure.  Exactly DCTSIZE+2 row groups of samples
  45.  * are allocated, but we create two different sets of pointers to this array.
  46.  * The second set swaps the last two pairs of row groups.  By working
  47.  * alternately with the two sets of pointers, we can access the data in the
  48.  * desired order.
  49.  */
  50.  
  51.  
  52.  
  53. /*
  54.  * Utility routines: common code for pipeline controllers
  55.  */
  56.  
  57. LOCAL void
  58. interleaved_scan_setup (compress_info_ptr cinfo)
  59. /* Compute all derived info for an interleaved (multi-component) scan */
  60. /* On entry, cinfo->comps_in_scan and cinfo->cur_comp_info[] are set up */
  61. {
  62.   short ci, mcublks;
  63.   jpeg_component_info *compptr;
  64.  
  65.   if (cinfo->comps_in_scan > MAX_COMPS_IN_SCAN)
  66.     ERREXIT(cinfo->emethods, "Too many components for interleaved scan");
  67.  
  68.   cinfo->MCUs_per_row = (cinfo->image_width
  69.              + cinfo->max_h_samp_factor*DCTSIZE - 1)
  70.             / (cinfo->max_h_samp_factor*DCTSIZE);
  71.  
  72.   cinfo->MCU_rows_in_scan = (cinfo->image_height
  73.                  + cinfo->max_v_samp_factor*DCTSIZE - 1)
  74.                 / (cinfo->max_v_samp_factor*DCTSIZE);
  75.   
  76.   cinfo->blocks_in_MCU = 0;
  77.  
  78.   for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
  79.     compptr = cinfo->cur_comp_info[ci];
  80.     /* for interleaved scan, sampling factors give # of blocks per component */
  81.     compptr->MCU_width = compptr->h_samp_factor;
  82.     compptr->MCU_height = compptr->v_samp_factor;
  83.     compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height;
  84.     /* compute physical dimensions of component */
  85.     compptr->downsampled_width = jround_up(compptr->true_comp_width,
  86.                        (long) (compptr->MCU_width*DCTSIZE));
  87.     compptr->downsampled_height = jround_up(compptr->true_comp_height,
  88.                         (long) (compptr->MCU_height*DCTSIZE));
  89.     /* Sanity check */
  90.     if (compptr->downsampled_width !=
  91.     (cinfo->MCUs_per_row * (compptr->MCU_width*DCTSIZE)))
  92.       ERREXIT(cinfo->emethods, "I'm confused about the image width");
  93.     /* Prepare array describing MCU composition */
  94.     mcublks = compptr->MCU_blocks;
  95.     if (cinfo->blocks_in_MCU + mcublks > MAX_BLOCKS_IN_MCU)
  96.       ERREXIT(cinfo->emethods, "Sampling factors too large for interleaved scan");
  97.     while (mcublks-- > 0) {
  98.       cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci;
  99.     }
  100.   }
  101.  
  102.   /* Convert restart specified in rows to actual MCU count. */
  103.   /* Note that count must fit in 16 bits, so we provide limiting. */
  104.   if (cinfo->restart_in_rows > 0) {
  105.     long nominal = cinfo->restart_in_rows * cinfo->MCUs_per_row;
  106.     cinfo->restart_interval = (UINT16) MIN(nominal, 65535L);
  107.   }
  108.  
  109.   (*cinfo->methods->c_per_scan_method_selection) (cinfo);
  110. }
  111.  
  112.  
  113. LOCAL void
  114. noninterleaved_scan_setup (compress_info_ptr cinfo)
  115. /* Compute all derived info for a noninterleaved (single-component) scan */
  116. /* On entry, cinfo->comps_in_scan = 1 and cinfo->cur_comp_info[0] is set up */
  117. {
  118.   jpeg_component_info *compptr = cinfo->cur_comp_info[0];
  119.  
  120.   /* for noninterleaved scan, always one block per MCU */
  121.   compptr->MCU_width = 1;
  122.   compptr->MCU_height = 1;
  123.   compptr->MCU_blocks = 1;
  124.   /* compute physical dimensions of component */
  125.   compptr->downsampled_width = jround_up(compptr->true_comp_width,
  126.                      (long) DCTSIZE);
  127.   compptr->downsampled_height = jround_up(compptr->true_comp_height,
  128.                       (long) DCTSIZE);
  129.  
  130.   cinfo->MCUs_per_row = compptr->downsampled_width / DCTSIZE;
  131.   cinfo->MCU_rows_in_scan = compptr->downsampled_height / DCTSIZE;
  132.  
  133.   /* Prepare array describing MCU composition */
  134.   cinfo->blocks_in_MCU = 1;
  135.   cinfo->MCU_membership[0] = 0;
  136.  
  137.   /* Convert restart specified in rows to actual MCU count. */
  138.   /* Note that count must fit in 16 bits, so we provide limiting. */
  139.   if (cinfo->restart_in_rows > 0) {
  140.     long nominal = cinfo->restart_in_rows * cinfo->MCUs_per_row;
  141.     cinfo->restart_interval = (UINT16) MIN(nominal, 65535L);
  142.   }
  143.  
  144.   (*cinfo->methods->c_per_scan_method_selection) (cinfo);
  145. }
  146.  
  147.  
  148.  
  149. LOCAL void
  150. alloc_sampling_buffer (compress_info_ptr cinfo, JSAMPIMAGE fullsize_data[2],
  151.                long fullsize_width)
  152. /* Create a pre-downsampling data buffer having the desired structure */
  153. /* (see comments at head of file) */
  154. {
  155.   short ci, vs, i;
  156.  
  157.   vs = cinfo->max_v_samp_factor; /* row group height */
  158.  
  159.   /* Get top-level space for array pointers */
  160.   fullsize_data[0] = (JSAMPIMAGE) (*cinfo->emethods->alloc_small)
  161.                 (cinfo->num_components * SIZEOF(JSAMPARRAY));
  162.   fullsize_data[1] = (JSAMPIMAGE) (*cinfo->emethods->alloc_small)
  163.                 (cinfo->num_components * SIZEOF(JSAMPARRAY));
  164.  
  165.   for (ci = 0; ci < cinfo->num_components; ci++) {
  166.     /* Allocate the real storage */
  167.     fullsize_data[0][ci] = (*cinfo->emethods->alloc_small_sarray)
  168.                 (fullsize_width,
  169.                 (long) (vs * (DCTSIZE+2)));
  170.     /* Create space for the scrambled-order pointers */
  171.     fullsize_data[1][ci] = (JSAMPARRAY) (*cinfo->emethods->alloc_small)
  172.                 (vs * (DCTSIZE+2) * SIZEOF(JSAMPROW));
  173.     /* Duplicate the first DCTSIZE-2 row groups */
  174.     for (i = 0; i < vs * (DCTSIZE-2); i++) {
  175.       fullsize_data[1][ci][i] = fullsize_data[0][ci][i];
  176.     }
  177.     /* Copy the last four row groups in swapped order */
  178.     for (i = 0; i < vs * 2; i++) {
  179.       fullsize_data[1][ci][vs*DCTSIZE + i] = fullsize_data[0][ci][vs*(DCTSIZE-2) + i];
  180.       fullsize_data[1][ci][vs*(DCTSIZE-2) + i] = fullsize_data[0][ci][vs*DCTSIZE + i];
  181.     }
  182.   }
  183. }
  184.  
  185.  
  186. LOCAL void
  187. free_sampling_buffer (compress_info_ptr cinfo, JSAMPIMAGE fullsize_data[2])
  188. /* Release a sampling buffer created by alloc_sampling_buffer */
  189. {
  190.   short ci;
  191.  
  192.   for (ci = 0; ci < cinfo->num_components; ci++) {
  193.     /* Free the real storage */
  194.     (*cinfo->emethods->free_small_sarray) (fullsize_data[0][ci]);
  195.     /* Free the scrambled-order pointers */
  196.     (*cinfo->emethods->free_small) ((void *) fullsize_data[1][ci]);
  197.   }
  198.  
  199.   /* Free the top-level space */
  200.   (*cinfo->emethods->free_small) ((void *) fullsize_data[0]);
  201.   (*cinfo->emethods->free_small) ((void *) fullsize_data[1]);
  202. }
  203.  
  204.  
  205.  
  206. LOCAL void
  207. downsample (compress_info_ptr cinfo,
  208.         JSAMPIMAGE fullsize_data, JSAMPIMAGE sampled_data,
  209.         long fullsize_width,
  210.         short above, short current, short below, short out)
  211. /* Do downsampling of a single row group (of each component). */
  212. /* above, current, below are indexes of row groups in fullsize_data;      */
  213. /* out is the index of the target row group in sampled_data.              */
  214. /* Special case: above, below can be -1 to indicate top, bottom of image. */
  215. {
  216.   jpeg_component_info *compptr;
  217.   JSAMPARRAY above_ptr, below_ptr;
  218.   JSAMPROW dummy[MAX_SAMP_FACTOR]; /* for downsample expansion at top/bottom */
  219.   short ci, vs, i;
  220.  
  221.   vs = cinfo->max_v_samp_factor; /* row group height */
  222.  
  223.   for (ci = 0; ci < cinfo->num_components; ci++) {
  224.     compptr = & cinfo->comp_info[ci];
  225.  
  226.     if (above >= 0)
  227.       above_ptr = fullsize_data[ci] + above * vs;
  228.     else {
  229.       /* Top of image: make a dummy above-context with copies of 1st row */
  230.       /* We assume current=0 in this case */
  231.       for (i = 0; i < vs; i++)
  232.     dummy[i] = fullsize_data[ci][0];
  233.       above_ptr = (JSAMPARRAY) dummy; /* possible near->far pointer conv */
  234.     }
  235.  
  236.     if (below >= 0)
  237.       below_ptr = fullsize_data[ci] + below * vs;
  238.     else {
  239.       /* Bot of image: make a dummy below-context with copies of last row */
  240.       for (i = 0; i < vs; i++)
  241.     dummy[i] = fullsize_data[ci][(current+1)*vs-1];
  242.       below_ptr = (JSAMPARRAY) dummy; /* possible near->far pointer conv */
  243.     }
  244.  
  245.     (*cinfo->methods->downsample[ci])
  246.         (cinfo, (int) ci,
  247.          fullsize_width, (int) vs,
  248.          compptr->downsampled_width, (int) compptr->v_samp_factor,
  249.          above_ptr,
  250.          fullsize_data[ci] + current * vs,
  251.          below_ptr,
  252.          sampled_data[ci] + out * compptr->v_samp_factor);
  253.   }
  254. }
  255.  
  256.  
  257. /* These variables are initialized by the pipeline controller for use by
  258.  * MCU_output_catcher.
  259.  * To avoid a lot of row-pointer overhead, we cram as many MCUs into each
  260.  * row of whole_scan_MCUs as we can get without exceeding 32Kbytes per row.
  261.  * NOTE: the "arbitrary" constant here must not exceed MAX_ALLOC_CHUNK
  262.  * defined in jmemsys.h, which is 64K-epsilon in most DOS implementations.
  263.  */
  264.  
  265. #define MAX_WHOLE_ROW_BLOCKS    ((int) (32768L / SIZEOF(JBLOCK))) /* max blocks/row */
  266.  
  267. static big_barray_ptr whole_scan_MCUs; /* Big array for saving the MCUs */
  268. static int MCUs_in_big_row;    /* # of MCUs in each row of whole_scan_MCUs */
  269. static long next_whole_row;    /* next row to access in whole_scan_MCUs */
  270. static int next_MCU_index;    /* next MCU in current row */
  271.  
  272.  
  273. METHODDEF void
  274. MCU_output_catcher (compress_info_ptr cinfo, JBLOCK *MCU_data)
  275. /* Output method for siphoning off extract_MCUs output into a big array */
  276. {
  277.   static JBLOCKARRAY rowptr;
  278.  
  279.   if (next_MCU_index >= MCUs_in_big_row) {
  280.     rowptr = (*cinfo->emethods->access_big_barray) (whole_scan_MCUs,
  281.                             next_whole_row, TRUE);
  282.     next_whole_row++;
  283.     next_MCU_index = 0;
  284.   }
  285.  
  286.   /*
  287.    * note that on 80x86, the cast applied to MCU_data implies
  288.    * near to far pointer conversion.
  289.    */
  290.   jcopy_block_row((JBLOCKROW) MCU_data,
  291.           rowptr[0] + next_MCU_index * cinfo->blocks_in_MCU,
  292.           (long) cinfo->blocks_in_MCU);
  293.   next_MCU_index++;
  294. }
  295.  
  296.  
  297. METHODDEF void
  298. dump_scan_MCUs (compress_info_ptr cinfo, MCU_output_method_ptr output_method)
  299. /* Dump the MCUs saved in whole_scan_MCUs to the output method. */
  300. /* The method may be either the entropy encoder or some routine supplied */
  301. /* by the entropy optimizer. */
  302. {
  303.   /* On an 80x86 machine, the entropy encoder expects the passed data block
  304.    * to be in NEAR memory (for performance reasons), so we have to copy it
  305.    * back from the big array to a local array.  On less brain-damaged CPUs
  306.    * we needn't do that.
  307.    */
  308. #ifdef NEED_FAR_POINTERS
  309.   JBLOCK MCU_data[MAX_BLOCKS_IN_MCU];
  310. #endif
  311.   long mcurow, mcuindex, next_row;
  312.   int next_index;
  313.   JBLOCKARRAY rowptr = NULL;    /* init only to suppress compiler complaint */
  314.  
  315.   next_row = 0;
  316.   next_index = MCUs_in_big_row;
  317.  
  318.   for (mcurow = 0; mcurow < cinfo->MCU_rows_in_scan; mcurow++) {
  319.     (*cinfo->methods->progress_monitor) (cinfo, mcurow,
  320.                      cinfo->MCU_rows_in_scan);
  321.     for (mcuindex = 0; mcuindex < cinfo->MCUs_per_row; mcuindex++) {
  322.       if (next_index >= MCUs_in_big_row) {
  323.     rowptr = (*cinfo->emethods->access_big_barray) (whole_scan_MCUs,
  324.                             next_row, FALSE);
  325.     next_row++;
  326.     next_index = 0;
  327.       }
  328. #ifdef NEED_FAR_POINTERS
  329.       jcopy_block_row(rowptr[0] + next_index * cinfo->blocks_in_MCU,
  330.               (JBLOCKROW) MCU_data, /* casts near to far pointer! */
  331.               (long) cinfo->blocks_in_MCU);
  332.       (*output_method) (cinfo, MCU_data);
  333. #else
  334.       (*output_method) (cinfo, rowptr[0] + next_index * cinfo->blocks_in_MCU);
  335. #endif
  336.       next_index++;
  337.     }
  338.   }
  339.  
  340.   cinfo->completed_passes++;
  341. }
  342.  
  343.  
  344.  
  345. /*
  346.  * Compression pipeline controller used for single-scan files
  347.  * with no optimization of entropy parameters.
  348.  */
  349.  
  350. static
  351. /* Work buffer for pre-downsampling data (see comments at head of file) */
  352. JSAMPIMAGE    fullsize_data[2],
  353. /* Work buffer for downsampled data */
  354.         sampled_data;
  355.  
  356. void
  357. single_cc_buf_init(compress_info_ptr cinfo)
  358. {
  359.     if (fullsize_data[0])
  360.     free_sampling_buffer(cinfo, fullsize_data),
  361.     fullsize_data[0] = NULL;
  362.     if (sampled_data)    {
  363.     register int    ci;
  364.     for (ci=cinfo->num_components; ci--;)
  365.         (*cinfo->emethods->free_small_sarray)(sampled_data[ci]);
  366.     (*cinfo->emethods->free_small)(sampled_data);
  367.     sampled_data = NULL;
  368.     }
  369. }
  370.  
  371. METHODDEF void
  372. single_ccontroller (compress_info_ptr cinfo)
  373. {
  374.   int rows_in_mem;        /* # of sample rows in full-size buffers */
  375.   long fullsize_width;        /* # of samples per row in full-size buffers */
  376.   long cur_pixel_row;        /* counts # of pixel rows processed */
  377.   long mcu_rows_output;        /* # of MCU rows actually emitted */
  378.   int mcu_rows_per_loop;    /* # of MCU rows processed per outer loop */
  379.   int rows_this_time;
  380.   short ci, whichss, i;
  381.  
  382.   /* Prepare for single scan containing all components */
  383.   if (cinfo->num_components > MAX_COMPS_IN_SCAN)
  384.     ERREXIT(cinfo->emethods, "Too many components for interleaved scan");
  385.   cinfo->comps_in_scan = cinfo->num_components;
  386.   for (ci = 0; ci < cinfo->num_components; ci++) {
  387.     cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci];
  388.   }
  389.   if (cinfo->comps_in_scan == 1) {
  390.     noninterleaved_scan_setup(cinfo);
  391.     /* Vk block rows constitute the same number of MCU rows */
  392.     mcu_rows_per_loop = cinfo->cur_comp_info[0]->v_samp_factor;
  393.   } else {
  394.     interleaved_scan_setup(cinfo);
  395.     /* in an interleaved scan, one MCU row contains Vk block rows */
  396.     mcu_rows_per_loop = 1;
  397.   }
  398.   cinfo->total_passes++;
  399. /*  (*cinfo->methods->write_scan_header) (cinfo);       /* for multi_frame
  400. */
  401.  
  402.   /* Compute dimensions of full-size pixel buffers */
  403.   /* Note these are the same whether interleaved or not. */
  404.   rows_in_mem = cinfo->max_v_samp_factor * DCTSIZE;
  405.   fullsize_width = jround_up(cinfo->image_width,
  406.                  (long) (cinfo->max_h_samp_factor * DCTSIZE));
  407.  
  408.   /* Allocate working memory: */
  409.   /* fullsize_data is sample data before downsampling */
  410.   if (!fullsize_data[0])
  411.     alloc_sampling_buffer(cinfo, fullsize_data, fullsize_width);
  412.   /* sampled_data is sample data after downsampling */
  413.   if (!sampled_data)    {
  414.     sampled_data = (JSAMPIMAGE) (*cinfo->emethods->alloc_small)
  415.             (cinfo->num_components * SIZEOF(JSAMPARRAY));
  416.     for (ci = 0; ci < cinfo->num_components; ci++)
  417.         sampled_data[ci] = (*cinfo->emethods->alloc_small_sarray)
  418.             (cinfo->comp_info[ci].downsampled_width,
  419.             (long) (cinfo->comp_info[ci].v_samp_factor * DCTSIZE));
  420.   }
  421.  
  422.   /* Tell the memory manager to instantiate big arrays.
  423.    * We don't need any big arrays in this controller,
  424.    * but some other module (like the input file reader) may need one.
  425.    */
  426.   (*cinfo->emethods->alloc_big_arrays)
  427.     ((long) 0,                /* no more small sarrays */
  428.      (long) 0,                /* no more small barrays */
  429.      (long) 0);                /* no more "medium" objects */
  430.  
  431.   /* Initialize output file & do per-scan object init */
  432.  
  433.   (*cinfo->methods->write_scan_header) (cinfo);
  434.   cinfo->methods->entropy_output = cinfo->methods->write_jpeg_data;
  435.   (*cinfo->methods->entropy_encode_init) (cinfo);
  436.   (*cinfo->methods->downsample_init) (cinfo);
  437.   (*cinfo->methods->extract_init) (cinfo);
  438.  
  439.   /* Loop over input image: rows_in_mem pixel rows are processed per loop */
  440.  
  441.   mcu_rows_output = 0;
  442.   whichss = 1;            /* arrange to start with fullsize_data[0] */
  443.  
  444.   for (cur_pixel_row = 0; cur_pixel_row < cinfo->image_height;
  445.        cur_pixel_row += rows_in_mem) {
  446.     (*cinfo->methods->progress_monitor) (cinfo, cur_pixel_row,
  447.                      cinfo->image_height);
  448.  
  449.     whichss ^= 1;        /* switch to other fullsize_data buffer */
  450.     
  451.     /* Obtain rows_this_time pixel rows and expand to rows_in_mem rows. */
  452.     /* Then we have exactly DCTSIZE row groups for downsampling. */   
  453.     rows_this_time = (int) MIN((long) rows_in_mem,
  454.                    cinfo->image_height - cur_pixel_row);
  455.  
  456.     (*cinfo->methods->get_sample_rows) (cinfo, rows_this_time,
  457.                     fullsize_data[whichss]);
  458.     (*cinfo->methods->edge_expand) (cinfo,
  459.                     cinfo->image_width, rows_this_time,
  460.                     fullsize_width, rows_in_mem,
  461.                     fullsize_data[whichss]);
  462.     
  463.     /* Downsample the data (all components) */
  464.     /* First time through is a special case */
  465.     
  466.     if (cur_pixel_row) {
  467.       /* Downsample last row group of previous set */
  468.       downsample(cinfo, fullsize_data[whichss], sampled_data, fullsize_width,
  469.          (short) DCTSIZE, (short) (DCTSIZE+1), (short) 0,
  470.          (short) (DCTSIZE-1));
  471.       /* and dump the previous set's downsampled data */
  472.       (*cinfo->methods->extract_MCUs) (cinfo, sampled_data, 
  473.                        mcu_rows_per_loop,
  474.                        cinfo->methods->entropy_encode);
  475.       mcu_rows_output += mcu_rows_per_loop;
  476.       /* Downsample first row group of this set */
  477.       downsample(cinfo, fullsize_data[whichss], sampled_data, fullsize_width,
  478.          (short) (DCTSIZE+1), (short) 0, (short) 1,
  479.          (short) 0);
  480.     } else {
  481.       /* Downsample first row group with dummy above-context */
  482.       downsample(cinfo, fullsize_data[whichss], sampled_data, fullsize_width,
  483.          (short) (-1), (short) 0, (short) 1,
  484.          (short) 0);
  485.     }
  486.     /* Downsample second through next-to-last row groups of this set */
  487.     for (i = 1; i <= DCTSIZE-2; i++) {
  488.       downsample(cinfo, fullsize_data[whichss], sampled_data, fullsize_width,
  489.          (short) (i-1), (short) i, (short) (i+1),
  490.          (short) i);
  491.     }
  492.   } /* end of outer loop */
  493.   
  494.   /* Downsample the last row group with dummy below-context */
  495.   /* Note whichss points to last buffer side used */
  496.   downsample(cinfo, fullsize_data[whichss], sampled_data, fullsize_width,
  497.          (short) (DCTSIZE-2), (short) (DCTSIZE-1), (short) (-1),
  498.          (short) (DCTSIZE-1));
  499.   /* Dump the remaining data (may be less than full height if uninterleaved) */
  500.   (*cinfo->methods->extract_MCUs) (cinfo, sampled_data, 
  501.         (int) (cinfo->MCU_rows_in_scan - mcu_rows_output),
  502.         cinfo->methods->entropy_encode);
  503.  
  504.   /* Finish output file */
  505.   (*cinfo->methods->extract_term) (cinfo);
  506.   (*cinfo->methods->downsample_term) (cinfo);
  507.   (*cinfo->methods->entropy_encode_term) (cinfo);
  508.   (*cinfo->methods->write_scan_trailer) (cinfo);
  509.   cinfo->completed_passes++;
  510.  
  511.   /* Release working memory */
  512.   /* (no work -- we let free_all release what's needful) */
  513. }
  514.  
  515.  
  516. /*
  517.  * Compression pipeline controller used for single-scan files
  518.  * with optimization of entropy parameters.
  519.  */
  520.  
  521. #ifdef ENTROPY_OPT_SUPPORTED
  522.  
  523. METHODDEF void
  524. single_eopt_ccontroller (compress_info_ptr cinfo)
  525. {
  526.   int rows_in_mem;        /* # of sample rows in full-size buffers */
  527.   long fullsize_width;        /* # of samples per row in full-size buffers */
  528.   long cur_pixel_row;        /* counts # of pixel rows processed */
  529.   long mcu_rows_output;        /* # of MCU rows actually emitted */
  530.   int mcu_rows_per_loop;    /* # of MCU rows processed per outer loop */
  531.   /* Work buffer for pre-downsampling data (see comments at head of file) */
  532.   JSAMPIMAGE fullsize_data[2];
  533.   /* Work buffer for downsampled data */
  534.   JSAMPIMAGE sampled_data;
  535.   int rows_this_time;
  536.   int blocks_in_big_row;
  537.   short ci, whichss, i;
  538.  
  539.   /* Prepare for single scan containing all components */
  540.   if (cinfo->num_components > MAX_COMPS_IN_SCAN)
  541.     ERREXIT(cinfo->emethods, "Too many components for interleaved scan");
  542.   cinfo->comps_in_scan = cinfo->num_components;
  543.   for (ci = 0; ci < cinfo->num_components; ci++) {
  544.     cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci];
  545.   }
  546.   if (cinfo->comps_in_scan == 1) {
  547.     noninterleaved_scan_setup(cinfo);
  548.     /* Vk block rows constitute the same number of MCU rows */
  549.     mcu_rows_per_loop = cinfo->cur_comp_info[0]->v_samp_factor;
  550.   } else {
  551.     interleaved_scan_setup(cinfo);
  552.     /* in an interleaved scan, one MCU row contains Vk block rows */
  553.     mcu_rows_per_loop = 1;
  554.   }
  555.   cinfo->total_passes += 2;    /* entropy encoder must add # passes it uses */
  556.  
  557.   /* Compute dimensions of full-size pixel buffers */
  558.   /* Note these are the same whether interleaved or not. */
  559.   rows_in_mem = cinfo->max_v_samp_factor * DCTSIZE;
  560.   fullsize_width = jround_up(cinfo->image_width,
  561.                  (long) (cinfo->max_h_samp_factor * DCTSIZE));
  562.  
  563.   /* Allocate working memory: */
  564.   /* fullsize_data is sample data before downsampling */
  565.   alloc_sampling_buffer(cinfo, fullsize_data, fullsize_width);
  566.   /* sampled_data is sample data after downsampling */
  567.   sampled_data = (JSAMPIMAGE) (*cinfo->emethods->alloc_small)
  568.                 (cinfo->num_components * SIZEOF(JSAMPARRAY));
  569.   for (ci = 0; ci < cinfo->num_components; ci++) {
  570.     sampled_data[ci] = (*cinfo->emethods->alloc_small_sarray)
  571.             (cinfo->comp_info[ci].downsampled_width,
  572.              (long) (cinfo->comp_info[ci].v_samp_factor * DCTSIZE));
  573.   }
  574.  
  575.   /* Figure # of MCUs to be packed in a row of whole_scan_MCUs */
  576.   MCUs_in_big_row = MAX_WHOLE_ROW_BLOCKS / cinfo->blocks_in_MCU;
  577.   blocks_in_big_row = MCUs_in_big_row * cinfo->blocks_in_MCU;
  578.  
  579.   /* Request a big array: whole_scan_MCUs saves the MCU data for the scan */
  580.   whole_scan_MCUs = (*cinfo->emethods->request_big_barray)
  581.         ((long) blocks_in_big_row,
  582.          (long) (cinfo->MCUs_per_row * cinfo->MCU_rows_in_scan
  583.              + MCUs_in_big_row-1) / MCUs_in_big_row,
  584.          1L);        /* unit height is 1 row */
  585.  
  586.   next_whole_row = 0;        /* init output ptr for MCU_output_catcher */
  587.   next_MCU_index = MCUs_in_big_row; /* forces access on first call! */
  588.  
  589.   /* Tell the memory manager to instantiate big arrays */
  590.   (*cinfo->emethods->alloc_big_arrays)
  591.     ((long) 0,                /* no more small sarrays */
  592.      (long) 0,                /* no more small barrays */
  593.      (long) 0);                /* no more "medium" objects */
  594.  
  595.   /* Do per-scan object init */
  596.  
  597.   (*cinfo->methods->downsample_init) (cinfo);
  598.   (*cinfo->methods->extract_init) (cinfo);
  599.  
  600.   /* Loop over input image: rows_in_mem pixel rows are processed per loop */
  601.   /* MCU data goes into whole_scan_MCUs, not to the entropy encoder */
  602.  
  603.   mcu_rows_output = 0;
  604.   whichss = 1;            /* arrange to start with fullsize_data[0] */
  605.  
  606.   for (cur_pixel_row = 0; cur_pixel_row < cinfo->image_height;
  607.        cur_pixel_row += rows_in_mem) {
  608.     (*cinfo->methods->progress_monitor) (cinfo, cur_pixel_row,
  609.                      cinfo->image_height);
  610.  
  611.     whichss ^= 1;        /* switch to other fullsize_data buffer */
  612.     
  613.     /* Obtain rows_this_time pixel rows and expand to rows_in_mem rows. */
  614.     /* Then we have exactly DCTSIZE row groups for downsampling. */   
  615.     rows_this_time = (int) MIN((long) rows_in_mem,
  616.                    cinfo->image_height - cur_pixel_row);
  617.  
  618.     (*cinfo->methods->get_sample_rows) (cinfo, rows_this_time,
  619.                     fullsize_data[whichss]);
  620.     (*cinfo->methods->edge_expand) (cinfo,
  621.                     cinfo->image_width, rows_this_time,
  622.                     fullsize_width, rows_in_mem,
  623.                     fullsize_data[whichss]);
  624.     
  625.     /* Downsample the data (all components) */
  626.     /* First time through is a special case */
  627.     
  628.     if (cur_pixel_row) {
  629.       /* Downsample last row group of previous set */
  630.       downsample(cinfo, fullsize_data[whichss], sampled_data, fullsize_width,
  631.          (short) DCTSIZE, (short) (DCTSIZE+1), (short) 0,
  632.          (short) (DCTSIZE-1));
  633.       /* and dump the previous set's downsampled data */
  634.       (*cinfo->methods->extract_MCUs) (cinfo, sampled_data, 
  635.                        mcu_rows_per_loop,
  636.                        MCU_output_catcher);
  637.       mcu_rows_output += mcu_rows_per_loop;
  638.       /* Downsample first row group of this set */
  639.       downsample(cinfo, fullsize_data[whichss], sampled_data, fullsize_width,
  640.          (short) (DCTSIZE+1), (short) 0, (short) 1,
  641.          (short) 0);
  642.     } else {
  643.       /* Downsample first row group with dummy above-context */
  644.       downsample(cinfo, fullsize_data[whichss], sampled_data, fullsize_width,
  645.          (short) (-1), (short) 0, (short) 1,
  646.          (short) 0);
  647.     }
  648.     /* Downsample second through next-to-last row groups of this set */
  649.     for (i = 1; i <= DCTSIZE-2; i++) {
  650.       downsample(cinfo, fullsize_data[whichss], sampled_data, fullsize_width,
  651.          (short) (i-1), (short) i, (short) (i+1),
  652.          (short) i);
  653.     }
  654.   } /* end of outer loop */
  655.   
  656.   /* Downsample the last row group with dummy below-context */
  657.   /* Note whichss points to last buffer side used */
  658.   downsample(cinfo, fullsize_data[whichss], sampled_data, fullsize_width,
  659.          (short) (DCTSIZE-2), (short) (DCTSIZE-1), (short) (-1),
  660.          (short) (DCTSIZE-1));
  661.   /* Dump the remaining data (may be less than full height if uninterleaved) */
  662.   (*cinfo->methods->extract_MCUs) (cinfo, sampled_data, 
  663.         (int) (cinfo->MCU_rows_in_scan - mcu_rows_output),
  664.         MCU_output_catcher);
  665.  
  666.   /* Clean up after that stuff, then find the optimal entropy parameters */
  667.  
  668.   (*cinfo->methods->extract_term) (cinfo);
  669.   (*cinfo->methods->downsample_term) (cinfo);
  670.   (*cinfo->emethods->free_small) (sampled_data);    /* for multi_frame */
  671.  
  672.   cinfo->completed_passes++;
  673.  
  674.   (*cinfo->methods->entropy_optimize) (cinfo, dump_scan_MCUs);
  675.  
  676.   /* Emit scan to output file */
  677.   /* Note: we can't do write_scan_header until entropy parameters are set! */
  678.  
  679.   (*cinfo->methods->write_scan_header) (cinfo);
  680.   cinfo->methods->entropy_output = cinfo->methods->write_jpeg_data;
  681.   (*cinfo->methods->entropy_encode_init) (cinfo);
  682.   dump_scan_MCUs(cinfo, cinfo->methods->entropy_encode);
  683.   (*cinfo->methods->entropy_encode_term) (cinfo);
  684.   (*cinfo->methods->write_scan_trailer) (cinfo);
  685.  
  686.   /* Release working memory */
  687.   /* (no work -- we let free_all release what's needful) */
  688. }
  689.  
  690. #endif /* ENTROPY_OPT_SUPPORTED */
  691.  
  692.  
  693. /*
  694.  * Compression pipeline controller used for multiple-scan files
  695.  * with no optimization of entropy parameters.
  696.  */
  697.  
  698. #ifdef C_MULTISCAN_FILES_SUPPORTED
  699.  
  700. METHODDEF void
  701. multi_ccontroller (compress_info_ptr cinfo)
  702. {
  703.   ERREXIT(cinfo->emethods, "Not implemented yet");
  704. }
  705.  
  706. #endif /* C_MULTISCAN_FILES_SUPPORTED */
  707.  
  708.  
  709. /*
  710.  * Compression pipeline controller used for multiple-scan files
  711.  * with optimization of entropy parameters.
  712.  */
  713.  
  714. #ifdef C_MULTISCAN_FILES_SUPPORTED
  715. #ifdef ENTROPY_OPT_SUPPORTED
  716.  
  717. METHODDEF void
  718. multi_eopt_ccontroller (compress_info_ptr cinfo)
  719. {
  720.   ERREXIT(cinfo->emethods, "Not implemented yet");
  721. }
  722.  
  723. #endif /* ENTROPY_OPT_SUPPORTED */
  724. #endif /* C_MULTISCAN_FILES_SUPPORTED */
  725.  
  726.  
  727. /*
  728.  * The method selection routine for compression pipeline controllers.
  729.  */
  730.  
  731. GLOBAL void
  732. jselcpipeline (compress_info_ptr cinfo)
  733. {
  734.   if (cinfo->interleave || cinfo->num_components == 1) {
  735.     /* single scan needed */
  736. #ifdef ENTROPY_OPT_SUPPORTED
  737.     if (cinfo->optimize_coding)
  738.       cinfo->methods->c_pipeline_controller = single_eopt_ccontroller;
  739.     else
  740. #endif
  741.       cinfo->methods->c_pipeline_controller = single_ccontroller;
  742.   } else {
  743.     /* multiple scans needed */
  744. #ifdef C_MULTISCAN_FILES_SUPPORTED
  745. #ifdef ENTROPY_OPT_SUPPORTED
  746.     if (cinfo->optimize_coding)
  747.       cinfo->methods->c_pipeline_controller = multi_eopt_ccontroller;
  748.     else
  749. #endif
  750.       cinfo->methods->c_pipeline_controller = multi_ccontroller;
  751. #else
  752.     ERREXIT(cinfo->emethods, "Multiple-scan support was not compiled");
  753. #endif
  754.   }
  755. }
  756.